﻿using System;
using System.Collections.Generic;
using System.Data.Entity.Validation;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Web.Mvc;
using Kugar.Core.ExtMethod;
using Kugar.Core.Web;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using WS.FlowAuth.Web.Data.EF;
using WS.FlowAuth.Web.Models.Home;

namespace WS.FlowAuth.Web.Controllers
{
    public class HomeController : BaseController
    {
        private static string _privateKey = "";

        static HomeController()
        {
            _privateKey =
                "<RSAKeyValue><Modulus>sr4C1OmHs6Rz/ND2t/dWRnO6fEjcczf0OHWDpjBMOL6pyUlsgsvXx6J/DAtiCKecAqwrfpibRzk9eu0LMZvYAEFar0LgLYwvZZL5uN0vBl6836Lfp6LNgdGJV/ika2Om8zLXGEU087XXMd7dlEYgs/41rFbOHvmWmX344VC/ric=</Modulus><Exponent>AQAB</Exponent><P>3DeSJ65NeERhHs3yjLCoHhyemcdhE70Wwdf5zZW9Oab+gKKXKArxWT4GZy2agreFclFeejBAIFwd5+dT4N/Nsw==</P><Q>z8kzLC0QwM+RGz1GKQ/xAh2lbmyogZDim8DVa0ZWlIDitDHmK4UiN5F0cYVTUa/zFafXlE+NX0vfxoF/RclrvQ==</Q><DP>s3wbhHn9LEPXQIss4FxvebNr1Px68+KO9Mj6EgS0aJPiJKfgOUPJ+CmkgF3b7CR2AHmvXjmLWpSZz1RsugDPHw==</DP><DQ>JYKl6UitaJFQGcHDA7CsCny9m6Sj+tfkAMgb/wSwpphp1KvZaGvdVHi+s6uk8e84i+VD5rNByz1QRW6lQjztZQ==</DQ><InverseQ>nhG8LADDPA1tptkh2dicVcTC5BC9ATb+s8peVECCZKGzkFbSer3ZOMTnJInICsmom5QkjRm5tCZDj9axSuAtag==</InverseQ><D>GesfSlQMt0TBrud23H6d65G3eR3a8vgqTo+NG1RF5oqQizK9lzUgy9QpJmF2LI7FZXEleMd/PgjeUeISl/XNux8EDpMiuD+IVlBke9UmmD+9Z6aPe9fgO4n4Vz6xZIXgiwbcG4SuZZ7pAKYBGZPvCgt0lqrtybcWcvsvm+Yyzb0=</D></RSAKeyValue>";

        }

        public ActionResult Index()
        {
            var key = Request.QueryString.Get("key");// Request.GetString("key");

            if (string.IsNullOrWhiteSpace(key))
            {
                return View("Error", new Model_Error() { ErrorMsg = "数据解码错误" });
            }

            var data = DecryptData(_privateKey, key);

            if (!string.IsNullOrWhiteSpace(data))
            {
                //数据格式:  随机码|流量计序号|机器码|操作码|用户代码|操作数据

                var strs = data.Split('|');

                var random = strs[0];
                var flowNo = strs[1];
                var machineName = strs[2];
                var optCode = strs[3];
                var userCode = strs[4];
                var optDataStr = strs[5];
                var optData = Convert.FromBase64String(optDataStr);//strs[5];

                var newOptData = //JoinToString(optData,"",0,optData.Length,"X2");
                    WS.FlowAuth.Converter.Converter.ParseOpData(optCode, optData);

                var userCodeData = Context.base_UserCode.Where(x => x.UserCode == userCode && !x.IsDeleted && x.ExpireDt>DateTime.Now).FirstOrDefault();

                if (userCodeData == null)
                {
                    return View("Error", new Model_Error() { ErrorMsg = "用户代码不存在或已过期,请联系管理员" });
                }

                var d = $"random={random}|OptData={strs[5]}".MD5_32Array();

                var authCoode = d.JoinToString("",0,d.Length,"D2").Left(8);

                var endDt = DateTime.Now.AddMinutes(1);

                var startDt = DateTime.Now.AddMinutes(-1);

                var url = this.Request.RawUrl;

                var urlLength = url.Length;

                if (urlLength>2047)
                {
                    urlLength = 2047;
                }

                if (!Context.log_AuthCode.Any(x=>x.CreateDt>= startDt && x.CreateDt<= endDt && x.RandomCode==random && x.UserCodeID==userCodeData.UserCodeID))
                {
                    var log = new log_AuthCode()
                    {
                        RandomCode = random,
                        FlowNo = flowNo,
                        MachineCode = machineName,
                        OptCode = optCode,
                        UserCodeID = userCodeData.UserCodeID,
                        OptData = optDataStr,//newOptData,
                        Url = this.Request.RawUrl.Substring(0, urlLength),
                        AuthCode = authCoode,
                        CreateDt = DateTime.Now,

                    };

                    

                    Context.log_AuthCode.Add(log);

                    try
                    {
                        Context.SaveChanges();

                    }
                    catch (DbEntityValidationException e)
                    {
                        var jarray=new JArray();

                        foreach (var error in e.EntityValidationErrors)
                        {
                            foreach (var validationError in error.ValidationErrors)
                            {
                                jarray.Add(validationError);
                            }
                            //jarray.Add(error.ValidationErrors);
                        }
                        
                        return Content(jarray.ToStringEx());
                    }
                    catch (Exception e)
                    {
                        throw;
                        return View("Error", new Model_Error() {ErrorMsg = "保存记录出错"});

                        return Content("生成记录错误");
                    }
                }



                var model = new Model_Index()
                {
                    AuthCode = authCoode,
                    OptCode = WS.FlowAuth.Converter.Converter.ConvertOpCode(optCode),
                    FlowNo = flowNo,
                    UserCode = userCode,
                    OptData =  newOptData
                };

                return View(model);

            }
            else
            {
                return View("Error", new Model_Error() { ErrorMsg = "数据解码错误" });
            }

        }

        public static string DecryptData(string privateKey,string encryptContent,  int decryptionBufferSize = 128)
        {
            try
            {
                var data = Convert.FromBase64String(encryptContent);

                using (var rsa = new RSACryptoServiceProvider())
                {
                    rsa.FromXmlString(privateKey);
                    using (var ms = new MemoryStream(data.Length))
                    {
                        if (decryptionBufferSize>data.Length)
                        {
                            decryptionBufferSize = data.Length;
                        }

                        byte[] buffer = new byte[decryptionBufferSize];
                        int pos = 0;
                        int copyLength = buffer.Length;

                        while (true)
                        {
                            Array.Copy(data, pos, buffer, 0, copyLength);
                            pos += copyLength;
                            byte[] resp = rsa.Decrypt(buffer, false);
                            ms.Write(resp, 0, resp.Length);
                            Array.Clear(resp, 0, resp.Length);
                            Array.Clear(buffer, 0, copyLength);
                            if (pos >= data.Length)
                            {
                                break;
                            }
                        }
                        return Encoding.UTF8.GetString(ms.ToArray());
                    }                    
                }

            }
            catch (Exception ce)
            {
                return "";
            }
        }

        //public static string RSADecrypt(string privatekey, string content)
        //{
        //    try
        //    {
        //        using (var rsa = new RSACryptoServiceProvider())
        //        {
        //            byte[] cipherbytes;

        //            rsa.FromXmlString(privatekey);

        //            //var str = Encoding.UTF8.GetBytes(content);

        //            var str = Convert.FromBase64String(content);

        //            cipherbytes = rsa.Decrypt(str, false);

        //            return Encoding.UTF8.GetString(cipherbytes);
        //        }
        //    }
        //    catch (Exception e)
        //    {
        //        return "";


        //    }
        //}

        private static string JoinToString(byte[] n, string splite, int start, int length, string strformat)
        {
            if (n == null || n.Length <= 0 || start > n.Length || start < 0 || length <= 0 || start + length > n.Length)
            {
                return string.Empty;
            }

            var s = new StringBuilder(length * 2);

            for (int i = start; i < start + length; i++)
            {
                s.Append(n[i].ToString(strformat) + splite);
            }

            if (!string.IsNullOrWhiteSpace(splite))
            {
                s = s.Remove(s.Length - 1, splite.Length);
            }


            return s.ToString();
        }
    }
}